Skip to main content

Function Basics

I. Functions

Resources:

function favoriteAnimal(animal) {
return animal + " is my favorite animal!"
}

console.log(favoriteAnimal('Goat'));
  1. The function definition is written on the first line function favoriteAnimal().
  2. Parameters are the items listed between the parentheses () in the function declaration. Function arguments are the actual values we decide to pass to the function. → animal is the parameter in this case.
    • Sometimes, parameters are optional and you don’t have to specify them. Rest Parameter Syntax (...param1) allows the function to accept any number of arguments and gathers them into an array named param1.
    • You can assign the parameter to a default valuedefault parameters, a value that will be used when you don’t pass any argument to the function.
    function hello (name = "Someone"){
    console.log(`Hello ${name}!`);
    }
    hello("Ari"); // Hello Ari!
    hello(); // Hello Someone!
  3. The return value is the value a function returns when it completes. In this case, the function returns a string, specifically, Goat is my favorite animal!
    • Some functions don’t return any value, they’re called void functions.
    • A function with an empty return returns undefined.
  4. We call our function at the last line favoriteAnimal('Goat'), we’re passing the value 'Goat' inside the function.

1. Built-in Browser Functions

JavaScript has many built-in functions to allow you to do useful things without having to write all that code yourself.

const myNumber = Math.random(); 
// the random() function generates a random number

const myText = "I am a string";
const newString = myText.replace("string", "a bunch of words");
// manipulate a string with the replace() function

2. Anonymous Functions

// normal function
function myFunction(){
console.log("Hello!");
}

// a function without a name
// anonymous function
(function (){
console.log("Hello!");
})

You’ll often use an anonymous function when another function expects to receive another function as a parameter. The function parameter is often passed as an anonymous function. → callback function

3. Callback Functions

A callback function is a function passed as an argument to another function, with the intention of being executed later. It allows one function to call another function at a specific time or after a certain task is completed.

// declare the greet() function
function greet(name, display){
const message = "Hello" + name;

// invoke callback function
display(message);
}

// declare the callback function
function displayMessage(message){
console.log(message);
}

// call the greet() function
// here you're passing the reference to displayMessage callback function
// not calling the displayMessage() function directly
greet("Alice", displayMessage);

4. [[02. Factory Functions and the Module Pattern#I. Scopes|Function Scope]]

When you create a function, the variables and other things defined inside the function exist only within the scope of that function, unreachable by the code outside the functions.

The top-level outside all functions is called the global scope, values defined in the global scope is accessible everywhere in the code.

const name = "Chris"; // global variable
function greeting() {
const company = "Google"; //local variable
console.log(`Hello ${name}: welcome to ${company}.`);
}
greeting();
console.log(company);
// nothing because the local variable company exists only within the scope of the greeting() function

5. Function Expression vs Function Declaration

1. Function Declaration

A function declaration is a function, declared as a separate statement, in the main code flow.

function sum(a, b){
return a + b;
}
  • A function declaration can be called earlier than it is defined because a global function declaration is created when JavaScript is preparing to start the script (hosting)→ it is visible in the whole script, no matter where it is.
// called before declaration
// the function can still be called even though it hasn't been declared
// this is thanks to hoisting
sayHi("John"); // Hello, John

// function declaration
function sayHi(name){
console.log(`Hello, ${name}`);
}

2. Function Expression

A function expression is a function, created inside an expression or another syntax construct.

// assigns the return value of the function to variable sum
let sum = function(a, b){
return a + b;
};
  • Function expressions are created when the execution reaches them.
// called before the expression
sayHi("John"); // error!

// function declaration
let sayHi = function (name){
console.log(`Hello, ${name}`);
}

A use for function expression: Most of the time it’s preferred to use function declaration over function expression because of the flexibility. However, there are certain situations where using a function expression is better.

Example:

let age = prompt("What is your age?"); 

if(age < 18){
// declare function
function welcome(){
console.log("Hello!");
} else {
// declare function
function welcome(){
console.log("Greeting!");
}
}
}

welcome(); // error, function welcome is out of scope here → undefined

To make the welcome() function accessible from outside the if block, we can use function expression:

let age = prompt("What is your age?"); 
let welcome; // declare this variable globally

if (age < 18){
// function expression
welcome = function(){
console.log("Hello!");
}
} else{
// function expression
welcome = function(){
console.log("Greeting!");
}
}

welcome(); // Hello!

6. Arrow Function*

A simple and concise syntax for creating a function that’s often better than function expressions is called arrow functions.

// syntax, multiline arrow function
let sum = (a, b, c) => {
let result = a + b + c;
return result;
}

// it can become simpler, with no brackets, only one line
let sum = (a, b) => a + b;

// This arrow function is a shorter form of:
let sum = function(a, b) {
return a + b;
};

// if there's only one argument, the parentheses can be omitted
let double = n => n * 2;
// Example: 
// normal function
function myFunction(){
console.log("Hello!");
}

// arrow function
let myFunction = () => {
console.log("Hello!");
}

The function part 5 can now be rewritten using arrow function and conditional operator:

let age = prompt("What is your age?"); 

let welcome = (age < 18) ? () => console.log("Hello!") :
() => console.log("Greetings!");
welcome();

Note: Code readability is much more important than writing short code.

II. JavaScript Call Stack

Resources:

A call stack is a way for the JavaScript engine to manage the execution of function calls in a program. It has information on what function is currently being run and what functions are invoked from within that function.

The JavaScript engine uses the call stack to also manage execution contexts:

  • The global execution context.
  • Function execution context.

1. How it Works

Because it’s a stack, it works based on the principle: last-in-first-out (LIFO).

  1. When you execute a script, the JavaScript engine creates a global execution context and pushes it on top of the call stack.
  2. Whenever a function is called, the JavaScript engine creates a new function execution context, pushes it on top of the call stack, and starts executing the function.
  3. If a function calls another function, the JavaScript engine creates a new function execution context for the function being called and pushes it on top of the call stack.
  4. When the current function completes, the JavaScript engine pops it off the call stack and resumes the execution where it left off.
  5. The script will stop when the call stack is empty.**
Example:
function add (a, b){
return a + b;
}

function average(a, b){
let sum = add (a, b);
return sum / 2;
}

let x = average (10, 20);
Call Stack Visualization
1. When the JavaScript engine executes the script above, it places the global execution context main() or global() on the call stack2. The JavaScript engine executes the call to average(10, 20) and creates a function execution context for average(), pushing it on top of the call stack.
3. The average() function calls add() function → the JavaScript engine creates another function execution context for add(), places it on top of the call stack.4. The JavaScript engine finishes executing the add() function and pops it off the call stack.
5. The average() function is on top of the call stack, the JavaScript engine completes executing it and pops it off the call stack.6. The call stack stops executing when the call stack is empty.

2. Stack Overflow

The call stack has a fixed size, depending on the implementation of the host environment, either the web browser or Node.js. If the number of execution contexts exceeds the size of the stack, a stack overflow error will occur.

// example: 
// a recursive function that has no exit condition
// this will cause a stack overflow error

function fn(){
// calls itself, recursive
fn();
}

fn(); // stack overflow

3. Asynchronous JavaScript

JavaScript is a single-threaded programming language, unlike Java, or C++, etc. → The JavaScript engine has only one call stack.

  • When executing a script, the JavaScript engine executes code from top to bottom, line by line → synchronous.
  • To be more efficient, the JavaScript engine can execute other tasks while waiting for another task to be completedasynchronous. To do this, the JavaScript engine uses an event loop